/**
 * @(#)SimulatorApkdownloadServiceImpl.java 2017年2月28日
 * Copyright(C) 2015 ZHEXIN IT CO.,LTD. All rights reserved.
 */
package org.jsbd.boss.service.impl;

import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

import javax.net.ssl.SSLContext;

import org.apache.http.client.CookieStore;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.jsbd.boss.common.BusType;
import org.jsbd.boss.common.redis.RedisClient;
import org.jsbd.boss.domian.SimulatorUVConfig;
import org.jsbd.boss.service.ISimulatorHMService;
import org.jsbd.boss.util.ADPoolExecutor;
import org.jsbd.boss.util.CacheKey;
import org.jsbd.boss.util.PhoneUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.zhexinit.proxy.domain.HttpContext;
import com.zhexinit.proxy.domain.HttpProxyLog;
import com.zhexinit.proxy.domain.ProxyHost;
import com.zhexinit.proxy.util.ProxyHostUtils;

import edu.hziee.common.queue.DelayExecuteBuffer;

/**
 * 红星美凯龙app uv
 * 
 * @author <a href="mailto:zhangbinghua@zhexinit.com" >zbh</a>
 * @version 1.0.0
 */
@Service
public class SimulatorHMServiceImpl implements ISimulatorHMService {
	public static final Logger LOGGER = LoggerFactory.getLogger(SimulatorHMServiceImpl.class);

	@Autowired
	private RedisClient redisClient;

	private static final int ONE_DAY = 60 * 60 * 24;
	@Autowired
	private DelayExecuteBuffer<HttpProxyLog> zxHttpProxyLogBuffer;

	@Override
	public void simulatordownload(final SimulatorUVConfig config) throws Exception {

		// 伪ua
		for (int i = 0; i < config.getThreadnum(); i++) {

			FutureTask future = new FutureTask(new Callable<Boolean>() {
				public Boolean call() {
					String uvcountkey = getSuccessKey(config);
					try {
						redisClient.incrementBy(uvcountkey, 1, ONE_DAY);
						simulatorTask(config);
					} catch (Exception e) {
						LOGGER.error("InterruptedException: ", e);
					}
					return null;
				}

			});

			ADPoolExecutor.getPoolExeFuture(future);
		}

	}

	public String getSuccessKey(SimulatorUVConfig config) {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		Calendar cal = Calendar.getInstance();
		String date = df.format(cal.getTime());
		String id = config.getId();
		String uvcountkey = CacheKey.UV_TASK + id + "_" + date;
		return uvcountkey;
	}

	public Long getExeCount(SimulatorUVConfig config) {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		Calendar cal = Calendar.getInstance();
		String date = df.format(cal.getTime());
		String id = config.getId();
		String uvcountkey = CacheKey.UV_TASK + id + "_" + date;
		return redisClient.getLong(uvcountkey);
	}

	public void simulatorTask(SimulatorUVConfig config) {
		String release = PhoneUtil.getRelease();
		String hstype = PhoneUtil.getHstype();
		String build = PhoneUtil.getBuild();

		HttpContext httpContext = new HttpContext();
		httpContext.setOrderId(UUID.randomUUID().toString());
		httpContext.setProvinceId("-1");
		httpContext.setImsi(httpContext.getOrderId());
		httpContext.setBizType(BusType.HM_CHANNEL_DOWNLOADAPK.getMessage());
		httpContext.setStep(0);
		HttpProxyLog httpProxyLog = new HttpProxyLog();
		httpProxyLog.setHttpContext(httpContext);
		httpProxyLog.setUrl(config.getUrl());
		Map<String, String> headerMap = new HashMap<String, String>();
		headerMap.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
		headerMap.put("Accept-Encoding", "gzip,deflate");
		headerMap.put("Accept-Language", "zh-CN,en-US;q=0.8");
		headerMap.put("Accept-Charset", "utf-8, iso-8859-1, utf-16, gb2312, gbk, *;q=0.7");
		headerMap.put("Referer", "https://wap.mmall.com/QR_code?version=30015&channel=13366&version=30015");
		headerMap.put("User-Agent",
				"Mozilla/5.0 (Linux; U; Android " + release + "; zh-cn; " + hstype + " Build/" + build + ") AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30");

		httpProxyLog.setHeaderMap(headerMap);

		httpDownload(httpProxyLog, zxHttpProxyLogBuffer, true);
	}

	public static boolean httpDownload(HttpProxyLog httpProxyLog, DelayExecuteBuffer<HttpProxyLog> httpProxyLogBuffer, boolean https) {
		CloseableHttpClient client = null;
		if (https) {
			client = createHttpsClient();
		} else {
			client = HttpClients.custom().build();
		}
		HttpContext httpContext = httpProxyLog.getHttpContext();
		String provinceId = httpContext.getProvinceId();
		String imsi = httpContext.getImsi();
		ProxyHost proxyHost = ProxyHostUtils.getProxyHost(imsi, provinceId, 5, httpProxyLog.getHttpContext().getBizType());
		httpProxyLog.setIpConnect(proxyHost.getIp());
		httpProxyLog.getHeaderMap().put("Ip", proxyHost.getIp());

		long t = System.currentTimeMillis();

		String url = httpProxyLog.getUrl();
		try {
			Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost.getAddress(), proxyHost.getPort()));
			URLConnection conn = new URL(url).openConnection(proxy);

			Map<String, String> headerMap = httpProxyLog.getHeaderMap();
			Iterator iterator = headerMap.entrySet().iterator();
			while (iterator.hasNext()) {
				Map.Entry<String, String> e = (Entry<String, String>) iterator.next();
				conn.setRequestProperty(e.getKey(), e.getValue());
			}

			InputStream in = conn.getInputStream();
			// ByteArrayOutputStream out = new ByteArrayOutputStream();
			byte[] b = new byte[1024];
			int len = 0;
			if ((len = in.read(b)) > -1) {
				// out.write(b, 0, len);
				LOGGER.info("download success");
			}
			// FileUtil.writeBytes("d:/"+UUID.randomUUID()+".apk", out.toByteArray());
			// httpGet.releaseConnection();
			in.close();
			// out.close();

		} catch (Exception e) {
			LOGGER.error("http 代理请求失败 [{}]", httpProxyLog, e);
			return false;
		} finally {
			long t1 = System.currentTimeMillis();
			httpProxyLog.setReadTime(t1 - t);
			httpProxyLogBuffer.add(httpProxyLog);
		}
		return true;
	}

	private static CloseableHttpClient createHttpsClient() {

		SSLContext sslcontext = null;
		try {
			sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
		} catch (KeyManagementException e) {
			LOGGER.warn("Any warn msg that u want to write", e);
		} catch (NoSuchAlgorithmException e) {
			LOGGER.warn("Any warn msg that u want to write", e);
		} catch (KeyStoreException e) {
			LOGGER.warn("Any warn msg that u want to write", e);
		}
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
		CookieStore cookieStore = new BasicCookieStore();
		RequestConfig globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.BROWSER_COMPATIBILITY).build();
		HttpClientContext context = HttpClientContext.create();
		context.setCookieStore(cookieStore);
		CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(globalConfig).setDefaultCookieStore(cookieStore).setSSLSocketFactory(sslsf).build();

		return client;
	}

}
